using System;
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Spine.Unity;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;

#if UNITY_EDITOR
using UnityEditor;
#endif

[RequireComponent(typeof(CapsuleCollider2D))]
public class SkeletonTouchUtility : MonoBehaviour
{
    public SkeletonGraphic role;


    public SkeletonUtilityDragConstraint dragConstraint;
    public BoneFollowerGraphic follower;
    public SkeletonUtilityBone utilityBone;

    public List<SkeletonTouchUtilityEvent> pointerDownEvents = new(); //按下Event
    public List<SkeletonTouchUtilityEvent> pointerUpEvents = new(); //抬起Event
    public List<SkeletonTouchUtilityEvent> clickEvents = new(); //点击Event
    
    public List<SkeletonTouchUtilityEvent> dragStartEvents = new(); //开始拖拽Event
    public List<SkeletonTouchUtilityEvent> dragEvents = new(); //拖拽Event
    public List<SkeletonTouchUtilityEvent> dragEndEvents = new(); //结束拖拽Event
    
    public List<SkeletonTouchUtilityAreaTrigger> areaTriggers = new(); //区域Trigger，希望玩家拖拽到某个区域触发事件时配在这里

    public bool limitPosInArea;
    public bool limitArea;
    [Header("椭圆参数")] public float semiMajorAxis = 2f; // 长半轴
    public float semiMinorAxis = 1f; // 短半轴
    [Range(0, 360)] public float rotationAngle = 0f; // 旋转角度
    public Vector2 limitWorldPosition;

    private Coroutine enableCoroutine;
    private Coroutine disableCoroutine;
    private float _speed = 9f;

    private void Awake()
    {
        foreach (var trigger in areaTriggers)
        {
            trigger.Init();
        }
    }

    #region 点击事件

    public void OnPointerDown(Vector2 clickPos)
    {
        Debug.Log("按下");
        foreach (var trigger in pointerDownEvents)
        {
            trigger.Invoke(role);
        }
    }

    public void OnPointerUp(Vector2 clickPos)
    {
        Debug.Log("抬起");
        foreach (var trigger in pointerUpEvents)
        {
            trigger.Invoke(role);
        }
    }

    public void OnPointerClick(Vector2 clickPos)
    {
        Debug.Log("点击");
        foreach (var trigger in clickEvents)
        {
            trigger.Invoke(role);
        }
    }

    #endregion

    #region 拖拽事件

    public void OnBeginDrag(Vector2 prePos, Vector2 curPos)
    {
        Debug.Log("拖拽开始");

        StopCoroutine();
        enableCoroutine = StartCoroutine(EnableWeight());
        
        foreach (var dragStartEvent in dragStartEvents)
        {
            dragStartEvent.Invoke(role);
        }
    }
    
    public void OnDrag(Vector2 prePos, Vector2 curPos)
    {
        Debug.Log("拖拽");
        transform.position = new Vector3(curPos.x, curPos.y, transform.position.z);

        foreach (var trigger in areaTriggers)
        {
            trigger.Update(role, utilityBone, curPos);
        }
        
        foreach (var dragEvent in dragEvents)
        {
            dragEvent.Invoke(role);
        }
    }

    public void OnEndDrag(Vector2 prePos, Vector2 curPos)
    {
        Debug.Log("拖拽结束");

        StopCoroutine();
        disableCoroutine = StartCoroutine(DisableWeight());

        foreach (var areaTrigger in areaTriggers)
        {
            areaTrigger.Release(role, utilityBone, curPos);
        }
        
        foreach (var dragEndEvent in dragEndEvents)
        {
            dragEndEvent.Invoke(role);
        }
    }

    #endregion

    #region 区域限定

    public bool CheckLimitArea(Vector2 curPos)
    {
        if (limitArea)
        {
            return IsPointInEllipse(new Vector3(curPos.x, curPos.y, transform.position.z));
        }

        return true;
    }

    /// <summary>
    /// 椭圆坐标
    /// </summary>
    /// <param name="angle"></param>
    /// <param name="center"></param>
    /// <param name="rotation"></param>
    /// <returns></returns>
    private Vector3 GetEllipsePoint(float angle, Vector3 center, Quaternion rotation)
    {
        // 椭圆参数方程
        float x = semiMajorAxis * Mathf.Cos(angle);
        float y = semiMinorAxis * Mathf.Sin(angle);

        Vector3 point = new Vector3(x, y, 0);
        point = rotation * point; // 应用旋转
        point += center; // 应用位置

        return point;
    }

    /// <summary>
    /// 判断世界坐标点是否在椭圆内
    /// </summary>
    public bool IsPointInEllipse(Vector3 worldPoint)
    {
        // 将点转换到椭圆的局部坐标系
        Vector3 localPoint = worldPoint - new Vector3(limitWorldPosition.x, limitWorldPosition.y, transform.position.z);

        // 应用反向旋转
        Quaternion inverseRotation = Quaternion.Euler(0, 0, -rotationAngle);
        localPoint = inverseRotation * localPoint;

        // 椭圆方程: (x/a)^2 + (y/b)^2 <= 1
        float normalizedX = localPoint.x / semiMajorAxis;
        float normalizedY = localPoint.y / semiMinorAxis;

        return (normalizedX * normalizedX + normalizedY * normalizedY) <= 1f;
    }

    /// <summary>
    /// 限定世界坐标在圆内
    /// </summary>
    /// <param name="targetPosition"></param>
    /// <returns></returns>
    public Vector2 ApplySimpleEllipticalConstraint(Vector2 targetPosition)
    {
        // 将目标点转换到椭圆的局部坐标系
        Vector2 relativePos = targetPosition - limitWorldPosition;

        // 应用反向旋转
        float radians = -rotationAngle * Mathf.Deg2Rad;
        float cos = Mathf.Cos(radians);
        float sin = Mathf.Sin(radians);
        Vector2 rotatedPos = new Vector2(
            cos * relativePos.x - sin * relativePos.y,
            sin * relativePos.x + cos * relativePos.y
        );

        // 计算当前点到椭圆中心的距离（按椭圆比例）
        float ellipseDistance = (rotatedPos.x * rotatedPos.x) / (semiMajorAxis * semiMajorAxis * 0.9f) +
                                (rotatedPos.y * rotatedPos.y) / (semiMinorAxis * semiMinorAxis * 0.9f);

        // 如果点在椭圆外，将其拉回椭圆边界
        if (ellipseDistance > 1f)
        {
            float scale = 1f / Mathf.Sqrt(ellipseDistance);
            rotatedPos *= scale;
        }

        // 将点转换回世界坐标系
        Vector2 constrainedPos = new Vector2(
            cos * rotatedPos.x + sin * rotatedPos.y,
            -sin * rotatedPos.x + cos * rotatedPos.y
        );

        return constrainedPos + limitWorldPosition;
    }

    #endregion
    
    #region 控制权重更新

    private IEnumerator EnableWeight()
    {
        follower.enabled = false;
        while (dragConstraint.Weight < 1)
        {
            var time = Time.deltaTime;
            dragConstraint.Weight += time * _speed;
            yield return new WaitForSeconds(time);
        }

        dragConstraint.Weight = 1;
    }

    private IEnumerator DisableWeight()
    {
        while (dragConstraint.Weight > 0)
        {
            var time = Time.deltaTime;
            dragConstraint.Weight -= time * _speed;
            yield return new WaitForSeconds(time);
        }

        follower.enabled = true;
        dragConstraint.Weight = 0;
    }

    private void StopCoroutine()
    {
        if (disableCoroutine != null)
        {
            StopCoroutine(disableCoroutine);
            disableCoroutine = null;
        }

        if (enableCoroutine != null)
        {
            StopCoroutine(enableCoroutine);
            enableCoroutine = null;
        }
    }

    #endregion

    private void OnDrawGizmosSelected()
    {
        //绘制限定区域
#if UNITY_EDITOR
        if (limitArea)
        {
            Gizmos.color = Color.yellow;

            Vector3 center = new Vector3(limitWorldPosition.x, limitWorldPosition.y, transform.position.z);
            Quaternion rotation = Quaternion.Euler(0, 0, rotationAngle);

            Vector3 prevPoint = GetEllipsePoint(0, center, rotation);
            int segments = 32;
            for (int i = 1; i <= segments; i++)
            {
                float angle = 2f * Mathf.PI * i / segments;
                Vector3 newPoint = GetEllipsePoint(angle, center, rotation);

                Gizmos.DrawLine(prevPoint, newPoint);
                prevPoint = newPoint;
            }
        }

#endif
        //绘制触发器区域
        foreach (var dragTrigger in areaTriggers)
        {
            dragTrigger.OnDrawGizmosSelected(utilityBone);
        }
    }
}